using System;
using System.Collections.Generic;
using UnityEngine;
using XFABManager;

namespace XFGameFramework
{

    public class EventConfig {
        public string eventName;
        public Action<object[]> callback;
        public EventConfig(string eventName, Action<object[]> callback) { 
            this.callback = callback;
            this.eventName = eventName;
        }
    }


    [DisallowMultipleComponent]
    public abstract class View : MonoBehaviour
    {

        #region 字段

        internal bool loaded = false;

        #endregion

        #region 属性

        /// <summary>
        /// 唯一标识(只读)
        /// </summary>
        public int Id => GetInstanceID();

        /// <summary>
        /// 当前View所在的模块
        /// </summary>
        public Module Module { get; internal set; }

        /// <summary>
        /// 预制体名称
        /// </summary>
        internal string AssetName { get; set; }

        /// <summary>
        /// 监听的事件(如果需要监听事件,请在Awake中对该字段赋值)
        /// </summary>
        [Obsolete("已过时,请使用方法 view.RegisterEvent(string eventName, Action<object[]> callback) 代替! ")]
        protected EventConfig[] ListenerEvents { get; set; }

        /// <summary>
        /// 监听的事件
        /// </summary>
        private List<EventConfig> listenerEvents = null;

        /// <summary>
        /// 当前View对应的数据，在View被回收时，该数据也会被移除!
        /// </summary>
        public virtual Model Model { get; }
         
        #endregion

        #region 生命周期

        protected virtual void Start() {
            // 说明 View 被创建出来了 但是没有对 module 赋值,
            // 说明不是通过我们提供的接口创建的,有可能是直接拖出来的,这种情况可以查找它的父类View 
            // 如果是直接拖拽到场景中的View，OnLoaded回调不会触发，同时module为空，如果需要，可以通过参数的形式传递
            if (Module == null && transform.parent != null )
            {
                // 尝试去父节点中查找
                View view = transform.parent.GetComponentInParent<View>();
                if (view != null && view.Module != null)
                    Module = view.Module;
                
            }

            if (Module == null)
                Module = ModuleManager.GetCurrentModule();

            if (loaded == false) 
            {
                OnLoaded(null);
                loaded = true;
            }

        }

        protected virtual void OnDestroy()
        {
            if (Module != null)
            {
                // 移除View
                ViewManager.RemoveView(Module, this); 
            }
        }

        protected virtual void OnEnable()
        {
            RegisterEvents();
        }

        protected virtual void OnDisable()
        {
            UnRegisterEvents();
        }

        #endregion

        #region 方法

        /// <summary>
        /// 关闭View(这里的关闭并不是销毁,而是放到缓存池中,所以不用担心销毁和创建的开销)
        /// </summary>
        public virtual void Close()
        {
            if (this.IsDestroy()) return;
            if (gameObject.IsDestroy()) return; 
            loaded = false; 
            if (Module != null)
            {
                // 移除View
                ViewManager.RemoveView(Module, this);
                // 移除数据 
                ModelManager.RemoveModel(Module, Model);
            }

            GameObjectLoader.UnLoad(gameObject); 
        }


        /// <summary>
        /// 加载完成的回调(可以在当前方法中做一些数据更新的逻辑)
        /// </summary>
        /// <param name="param">加载View时传递的参数</param>
        public virtual void OnLoaded(params object[] param) 
        { 
        }

        /// <summary>
        /// View被回收 或 被移除时调用
        /// </summary>
        public virtual void OnRemove() {
            if (Module != null)
            { 
                // 移除数据 
                ModelManager.RemoveModel(Module, Model);
            }
        }

        private void RegisterEvents()
        {
            if (listenerEvents != null && listenerEvents.Count != 0) 
            {             
                foreach (var item in listenerEvents)
                    EventManager.AddEvent(item.eventName, item.callback);
            }


            // 判断是否有需要监听的事件
            if (ListenerEvents == null || ListenerEvents.Length == 0) return;

            foreach (var item in ListenerEvents)
                EventManager.AddEvent(item.eventName, item.callback);


        }

        private void UnRegisterEvents()
        {

            if (listenerEvents != null && listenerEvents.Count != 0) 
            {
                foreach (var item in listenerEvents)
                    EventManager.RemoveEvent(item.eventName, item.callback);
            }


            if (ListenerEvents == null || ListenerEvents.Length == 0) return;

            foreach (var item in ListenerEvents) 
                EventManager.RemoveEvent(item.eventName,item.callback); 
             
        }


        /// <summary>
        /// 添加View监听的事件
        /// (注:请在Awake中调用该方法,否则事件无法正常注册,
        /// 通过该方法添加事件无需处理移除逻辑,框架会自行管理!)
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="callback"></param>
        protected void RegisterEvent(string eventName, Action<object[]> callback) 
        {
            if (listenerEvents == null)
                listenerEvents = new List<EventConfig>();

            foreach (var item in listenerEvents)
            {
                if (item.eventName == eventName && item.callback == callback)
                    throw new Exception(string.Format("事件重复注册:eventName:{0} callback:{1}",eventName,callback.ToString()));
            }
             
            listenerEvents.Add(new EventConfig(eventName, callback));
        }

        #endregion
    }
}